package com.iwayin.core.bo.loginwith;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.json.JSONArray;
import org.json.JSONObject;

import weibo4j.Oauth;
import weibo4j.Users;
import weibo4j.Weibo;
import weibo4j.http.AccessToken;
import weibo4j.model.User;
import weibo4j.model.WeiboException;

import com.iwayin.core.dao.loginwith.LoginWithDAO;
import com.iwayin.core.dao.user.UserDAO;
import com.iwayin.core.dataobject.UserDO;
import com.iwayin.core.enumer.LoginWithEnum;
import com.iwayin.core.utils.DateTimeUtil;
import com.iwayin.core.utils.HttpURLUtils;
import com.iwayin.core.utils.PasswordUtil;
import com.iwayin.core.utils.StringUtil;
import com.iwayin.core.utils.MD5.TaoBaoMD5Signature;

/**
 * 
 * @author LiuWenLong
 * @version 待整理 工厂模式
 */
public class LoginWithBOImpl implements LoginWithBO {

	private LoginWithDAO loginWithDAO;
	private UserDAO userDAO;

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public UserDO addQQMember(String code) {
		UserDO user = null;
		HttpClient qqClient = new HttpClient();
		String qqGetTokenUrl = "https://graph.qq.com/oauth2.0/token?" + "grant_type=authorization_code" + "&client_id=" + LoginWithEnum.QQ.getAppKey() + "&client_secret="
				+ LoginWithEnum.QQ.getAppSecret() + "&code=" + code + "&state=123123" + "&redirect_uri=" + "http://yoasking.com/loginWith/loginWithTb.action";
		GetMethod method = new GetMethod(qqGetTokenUrl);
		try {
			// get token
			qqClient.executeMethod(method);
			String response = method.getResponseBodyAsString();
			String token = response.substring(13, response.indexOf("&"));

			// get openID
			String getOpenIdUrl = "https://graph.qq.com/oauth2.0/me?access_token=" + token;
			method = new GetMethod(getOpenIdUrl);
			qqClient.executeMethod(method);
			response = method.getResponseBodyAsString();
			response = response.substring(9, response.length() - 3);
			JSONObject callback = new JSONObject(response);
			String openId = obj2String(callback.get("openid"));

			// get user info
			String getUserInfoUrl = "https://graph.qq.com/user/get_user_info?" + "access_token=" + token + "&oauth_consumer_key=" + LoginWithEnum.QQ.getAppKey() + "&openid="
					+ openId;
			method = new GetMethod(getUserInfoUrl);
			qqClient.executeMethod(method);
			response = method.getResponseBodyAsString();
			JSONObject qqUser = new JSONObject(response);
			String nickname = obj2String(qqUser.get("nickname"));
			nickname = new String(nickname.getBytes("ISO-8859-1"), "utf-8");
			String avatar = obj2String(qqUser.get("figureurl_2"));
			Long gender;
			String tempGender = obj2String(qqUser.get("gender"));
			// 女：å¥³ 男:ç·
			if (tempGender.equals("å¥³")) {
				gender = UserDO.USER_GENDER_GIRL;
			} else {
				gender = UserDO.USER_GENDER_BOY;
			}

			Long userId = loginWithDAO.getQQMember(openId);
			Map qqMember = new HashMap();
			qqMember.put("userId", userId);
			qqMember.put("nickname", nickname);
			qqMember.put("avatar", avatar);
			qqMember.put("gender", gender);
			qqMember.put("token", token);
			qqMember.put("openId", openId);
			if (userId != null) {
				loginWithDAO.updateQQMember(qqMember);
			} else {
				userId = this.addQQVirtualUser(qqMember);
				qqMember.put("userId", userId);
				loginWithDAO.addQQMember(qqMember);
			}
			user = userDAO.getUserById(userId);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			method.releaseConnection();
		}
		return user;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public UserDO addTbMember(String code) {
		UserDO user = null;
		HttpClient tbClient = new HttpClient();
		String tbGetTokenUrl = "https://oauth.taobao.com/token?client_id=" + LoginWithEnum.TAOBAO.getAppKey() + "&client_secret=" + LoginWithEnum.TAOBAO.getAppSecret()
				+ "&grant_type=authorization_code&code=" + code + "&redirect_uri=http://yoasking.com/loginWith/loginWithTb.action&scope=item";
		PostMethod method = new PostMethod(tbGetTokenUrl);
		try {
			// get token
			tbClient.executeMethod(method);
			String response = method.getResponseBodyAsString();
			JSONObject tokenObj = new JSONObject(response);
			String token = tokenObj.getString("access_token");
			String nick = tokenObj.getString("taobao_user_nick");
			String openId = tokenObj.getString("taobao_user_id");
			// get openID
			String timestampStr = DateTimeUtil.getCurrDateTimeStr();
			String fields = "user_id,uid,nick,sex,avatar";
			TreeMap<String, String> params = new TreeMap<String, String>();
			params.put("app_key", LoginWithEnum.TAOBAO.getAppKey());
			params.put("fields", fields);
			params.put("format", "json");
			params.put("method", "taobao.user.get");
			params.put("nick", nick);
			params.put("sign_method", "md5");
			params.put("timestamp", timestampStr);
			params.put("v", "2.0");
			String sign = TaoBaoMD5Signature.md5Signature(params, LoginWithEnum.TAOBAO.getAppSecret());

			String tbUserInfoUrl = "http://gw.api.taobao.com/router/rest";
			method = new PostMethod(tbUserInfoUrl);
			method.setParameter("sign", sign);
			method.setParameter("app_key", LoginWithEnum.TAOBAO.getAppKey());
			method.setParameter("fields", fields);
			method.setParameter("format", "json");
			method.setParameter("method", "taobao.user.get");
			method.setParameter("nick", nick);
			method.setParameter("sign_method", "md5");
			method.setParameter("timestamp", timestampStr);
			method.setParameter("v", "2.0");
			tbClient.executeMethod(method);
			response = method.getResponseBodyAsString();
			JSONObject responseObj = new JSONObject(response);
			JSONObject tbUser = responseObj.getJSONObject("user_get_response").getJSONObject("user");

			String nickname = obj2String(tbUser.get("nick"));
			String avatar = obj2String(tbUser.get("avatar"));
			Long gender = UserDO.USER_GENDER_BOY;
			// String tempGender = obj2String(tbUser.get("sex"));
			// if (tempGender.equals("m")) {
			// gender = UserDO.USER_GENDER_BOY;
			// } else {
			// gender = UserDO.USER_GENDER_GIRL;
			// }

			Long userId = loginWithDAO.getTbMember(openId);
			Map tbMember = new HashMap();
			tbMember.put("nickname", nickname);
			tbMember.put("avatar", avatar);
			tbMember.put("gender", gender);
			tbMember.put("token", token);
			tbMember.put("openId", openId);
			if (userId != null) {
				tbMember.put("userId", userId);
				loginWithDAO.updateTbMember(tbMember);
			} else {
				userId = this.addTbVirtualUser(tbMember);
				tbMember.put("userId", userId);
				loginWithDAO.addTbMember(tbMember);
			}
			user = userDAO.getUserById(userId);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			method.releaseConnection();
		}
		return user;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public UserDO addSinaMember(String code) {
		try {
			Oauth oauth = new Oauth();
			AccessToken accessToken = oauth.getAccessTokenByCode(code);
			Long userId = null;
			try {
				String token = accessToken.getAccessToken();
				// 获取新浪用户信息
				Weibo weibo = new Weibo();
				weibo.setToken(token);
				Users um = new Users();
				String sinaUid = accessToken.getUid();
				User user = um.showUserById(sinaUid);
				String openId = user.getId();
				String nickname = user.getScreenName();
				String avatar = user.getAvatarLarge();
				Long gender;
				String tempGender = user.getGender();
				if (tempGender.equals("f")) {
					gender = UserDO.USER_GENDER_BOY;
				} else {
					gender = UserDO.USER_GENDER_GIRL;
				}

				userId = loginWithDAO.getSinaMember(openId);
				Map sinaMember = new HashMap();
				sinaMember.put("userId", userId);
				sinaMember.put("nickname", nickname);
				sinaMember.put("avatar", avatar);
				sinaMember.put("gender", gender);
				sinaMember.put("token", token);
				sinaMember.put("openId", openId);
				if (userId != null) {
					loginWithDAO.updateSinaMember(sinaMember);
				} else {
					userId = this.addSinaVirtualUser(sinaMember);
					sinaMember.put("userId", userId);
					loginWithDAO.addSinaMember(sinaMember);
				}
			} catch (WeiboException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
			return userDAO.getUserById(userId);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public UserDO addRenrenMember(String code) {
		try {
			String rrOAuthTokenEndpoint = "https://graph.renren.com/oauth/token";
			Map<String, String> parameters = new HashMap<String, String>();
			parameters.put("client_id", LoginWithEnum.RENREN.getAppKey());
			parameters.put("client_secret", LoginWithEnum.RENREN.getAppSecret());
			parameters.put("redirect_uri", "http://yoasking.com/loginWith/loginWithRenren.action");
			parameters.put("grant_type", "authorization_code");
			parameters.put("code", code);
			String tokenResult = HttpURLUtils.doPost(rrOAuthTokenEndpoint, parameters);
			Long userId = null;
			if(StringUtil.isNotBlank(tokenResult)){
				JSONObject responseObj = new JSONObject(tokenResult);
				String accessToken = (String) responseObj.get("access_token");
				String refreshToken = (String) responseObj.get("refresh_token");
				JSONObject rru = (JSONObject) responseObj.get("user");
				String uid = rru.getString("id");
				String name = rru.getString("name");
				JSONArray avatar = rru.getJSONArray("avatar");
				JSONObject a = avatar.getJSONObject(2);
				userId = loginWithDAO.getRenrenMember(uid);
				
				Map rrMember = new HashMap();
				rrMember.put("userId", userId);
				rrMember.put("rrUid", uid);
				rrMember.put("nickname", name);
				rrMember.put("avatar", a.getString("url"));
				rrMember.put("gender", 1);//随意默认
				rrMember.put("token", accessToken);
				rrMember.put("refresh", refreshToken);
				
				if(userId != null){
					loginWithDAO.updateRenrenMember(rrMember);
				}else{
					userId = this.addRenrenVirtualUser(rrMember);
					rrMember.put("userId", userId);
					loginWithDAO.addRenrenMember(rrMember);
				}
			}
			return userDAO.getUserById(userId);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private Long addRenrenVirtualUser(Map rrMember) {
		rrMember.put("platform", "RenRen");
		return this.addVirtualUser(rrMember);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private Long addTbVirtualUser(Map tbMember) {
		tbMember.put("platform", "TaoBao");
		return this.addVirtualUser(tbMember);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private Long addSinaVirtualUser(Map sinaMember) {
		sinaMember.put("platform", "Sina");
		return this.addVirtualUser(sinaMember);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Long addQQVirtualUser(Map qqMember) {
		qqMember.put("platform", "QQ");
		return this.addVirtualUser(qqMember);
	}

	@SuppressWarnings("rawtypes")
	private Long addVirtualUser(Map qqMember) {
		UserDO user = new UserDO();
		user.setNickname(qqMember.get("nickname").toString());
		UserDO isNickName = this.userDAO.getUserByNickName(user.getNickname());
		if (isNickName != null) {
			user.setNickname(user.getNickname() + PasswordUtil.getRandomOperPassword());
		}
		user.setGender(Long.valueOf(qqMember.get("gender").toString()));
		user.setAvatarPath(qqMember.get("avatar").toString());
		user.setStatus(UserDO.USER_NOT_ACTIVATE_STATUS);
		// 密码
		user.setLoginPwd("yoasking");
		String randomKey = PasswordUtil.getRandomOperPassword();
		user.setPwdKey(randomKey);
		user.setLoginPwd(PasswordUtil.getEncyptedOperPassword(user.getLoginPwd(), randomKey));
		return this.userDAO.addUser(user);
	}

	private String obj2String(Object obj) {
		if (obj == null) {
			return "";
		} else {
			return obj.toString();
		}
	}

	public void setLoginWithDAO(LoginWithDAO loginWithDAO) {
		this.loginWithDAO = loginWithDAO;
	}

	public void setUserDAO(UserDAO userDAO) {
		this.userDAO = userDAO;
	}

}
